commonlibsse_ng\re\i/
IMemoryHeap.rs

1use core::ffi::{c_char, c_void};
2
3use crate::re::offsets_rtti::RTTI_IMemoryHeap;
4use crate::re::offsets_vtable::VTABLE_IMemoryHeap;
5use crate::rel::id::VariantID;
6
7bitflags::bitflags! {
8    #[repr(transparent)]
9    #[derive(Debug, Default,Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
10    pub struct MEM_CONTEXT: u32 {}
11}
12
13/// Represents the `HeapStats` struct.
14#[repr(C)]
15#[derive(Debug, Clone, PartialEq)]
16pub struct HeapStats {
17    pub heapName: *const c_char,     // 0x00
18    pub memHeapSize: usize,          // 0x08
19    pub memHeapCommitted: usize,     // 0x10
20    pub memAllocatedToBlocks: usize, // 0x18
21    pub numBlocks: i32,              // 0x20
22    pub numFreeBlocks: i32,          // 0x24
23    pub memFreeInBlocks: usize,      // 0x28
24    pub memUsedInBlocks: usize,      // 0x30
25    pub smallestFreeBlock: usize,    // 0x38
26    pub largestFreeBlock: usize,     // 0x40
27    pub heapOverhead: usize,         // 0x48
28    pub freeListOverhead: usize,     // 0x50
29    pub blockOverhead: usize,        // 0x58
30    pub totalFree: usize,            // 0x60
31}
32
33const _: () = {
34    assert!(std::mem::size_of::<HeapStats>() == 0x68);
35};
36
37/// Memory heap interface
38#[repr(C)]
39pub struct IMemoryHeap {
40    pub vtable: *const IMemoryHeapVtbl,
41}
42
43#[repr(C)]
44pub struct IMemoryHeapVtbl {
45    pub CxxDrop: unsafe extern "C" fn(this: *mut IMemoryHeap), // 00
46
47    pub Size: unsafe extern "C" fn(this: *const IMemoryHeap, mem: *const c_void) -> usize, // 01
48    pub GetMemoryStats: unsafe extern "C" fn(this: *mut IMemoryHeap, stats: *mut HeapStats), // 02
49    pub ContainsBlockImpl:
50        unsafe extern "C" fn(this: *const IMemoryHeap, block: *const c_void) -> bool, // 03
51    pub AllocateAlignImpl:
52        unsafe extern "C" fn(this: *mut IMemoryHeap, size: usize, alignment: u32) -> *mut c_void, // 04
53    pub DeallocateAlignImpl: unsafe extern "C" fn(this: *mut IMemoryHeap, block: *mut *mut c_void), // 05
54
55    // IMemoryHeap-specific methods
56    pub GetName: unsafe extern "C" fn(this: *const IMemoryHeap) -> *const c_char, // 07
57    pub Allocate:
58        unsafe extern "C" fn(this: *mut IMemoryHeap, size: usize, alignment: u32) -> *mut c_void, // 08
59    pub Deallocate: unsafe extern "C" fn(this: *mut IMemoryHeap, mem: *mut c_void, alignment: u32), // 09
60    pub PointerInHeap:
61        unsafe extern "C" fn(this: *const IMemoryHeap, pointer: *const c_void) -> bool, // 0A
62    pub TotalSize: unsafe extern "C" fn(this: *const IMemoryHeap, pointer: *const c_void) -> usize, // 0B
63    pub GetHeapStats:
64        unsafe extern "C" fn(this: *mut IMemoryHeap, stats: *mut HeapStats, full_block_info: bool), // 0C
65    pub ShouldTrySmallBlockPools:
66        unsafe extern "C" fn(this: *const IMemoryHeap, size: usize, context: MEM_CONTEXT) -> bool, // 0D
67    pub GetPageSize: unsafe extern "C" fn(this: *const IMemoryHeap) -> u32, // 0E
68}
69
70impl IMemoryHeap {
71    /// Address & Offset of the runtime type information (RTTI) identifier.
72    pub const RTTI: VariantID = RTTI_IMemoryHeap;
73
74    /// Address & Offset of the virtual function table.
75    pub const VTABLE: [VariantID; 1] = VTABLE_IMemoryHeap;
76
77    /// Get the name of the heap.
78    ///
79    /// # Safety
80    pub unsafe fn get_name(&self) -> *const c_char {
81        unsafe { ((*self.vtable).GetName)(self) }
82    }
83
84    /// Allocate memory with alignment.
85    ///
86    /// # Safety
87    pub unsafe fn allocate(&mut self, size: usize, alignment: u32) -> *mut c_void {
88        unsafe { ((*self.vtable).Allocate)(self, size, alignment) }
89    }
90
91    /// Deallocate memory.
92    ///
93    /// # Safety
94    pub unsafe fn deallocate(&mut self, mem: *mut c_void, alignment: u32) {
95        unsafe { ((*self.vtable).Deallocate)(self, mem, alignment) };
96    }
97
98    /// Check if a pointer is in the heap.
99    ///
100    /// # Safety
101    pub unsafe fn pointer_in_heap(&self, pointer: *const c_void) -> bool {
102        unsafe { ((*self.vtable).PointerInHeap)(self, pointer) }
103    }
104
105    /// Get the total size of a block in the heap.
106    ///
107    /// # Safety
108    pub unsafe fn total_size(&self, pointer: *const c_void) -> usize {
109        unsafe { ((*self.vtable).TotalSize)(self, pointer) }
110    }
111
112    /// Get the heap statistics.
113    ///
114    /// # Safety
115    pub unsafe fn get_heap_stats(&mut self, stats: *mut HeapStats, full_block_info: bool) {
116        unsafe { ((*self.vtable).GetHeapStats)(self, stats, full_block_info) };
117    }
118
119    /// Check if small block pools should be tried.
120    ///
121    /// # Safety
122    pub unsafe fn should_try_small_block_pools(&self, size: usize, context: MEM_CONTEXT) -> bool {
123        unsafe { ((*self.vtable).ShouldTrySmallBlockPools)(self, size, context) }
124    }
125
126    /// Get the page size.
127    ///
128    /// # Safety
129    pub unsafe fn get_page_size(&self) -> u32 {
130        unsafe { ((*self.vtable).GetPageSize)(self) }
131    }
132}